#!/usr/bin/env python3
# multi_protocol_honeypot.py
# 多协议蜜罐（重构版）
# 支持协议：TCP（回显）、HTTP、HTTPS（TLS）、SSH（仅横幅）、Telnet、FTP（控制通道最小实现）
# 需要 Python 3.11+

import argparse
import asyncio
import logging
import sys
import time
import threading
from pathlib import Path

# ---------------------- 操作员日志记录和默认值 ----------------------
# 导入统一的日志模块
from multihoneypot.logger import op_logger
from multihoneypot.config import get_ports_config

DEFAULT_LOG_FILE = "honeypot_sessions.jsonl"

# ------------------------------------------------------------------------

def parse_args():
    """
    解析命令行参数

    Returns:
        argparse.Namespace: 解析后的命令行参数
    """
    p = argparse.ArgumentParser(description="多协议蜜罐")
    p.add_argument("--host", default="0.0.0.0", help="监听地址")
    p.add_argument("--log", default=DEFAULT_LOG_FILE)
    p.add_argument("--tcp-port", type=int, help="TCP端口")
    p.add_argument("--http-port", type=int, help="HTTP端口")
    p.add_argument("--https-port", type=int, help="HTTPS端口")
    p.add_argument("--ssh-port", type=int, help="SSH端口")
    p.add_argument("--telnet-port", type=int, help="Telnet端口")
    p.add_argument("--ftp-port", type=int, help="FTP端口")
    p.add_argument("--certfile", default="cert.pem", help="HTTPS证书（PEM格式）")
    p.add_argument("--keyfile", default="key.pem", help="HTTPS密钥（PEM格式）")
    p.add_argument("--generate-cert", action="store_true", help="如果缺失，尝试使用openssl自动创建自签名证书")
    p.add_argument("--config", default="config.ini", help="配置文件路径")
    return p.parse_args()

async def main_async():
    """
    异步主函数，负责初始化和运行蜜罐
    """
    # 将相对导入改为绝对导入
    from multihoneypot.config import load_config, get_ports_config
    from multihoneypot.manager import HoneypotManager, ensure_self_signed
    from multihoneypot.tcp_handler import TCPHandler
    from multihoneypot.http_handler import HTTPHandler
    from multihoneypot.https_handler import HTTPSHandler
    from multihoneypot.ssh_handler import SSHHandler
    from multihoneypot.telnet_handler import TelnetHandler
    from multihoneypot.ftp_handler import FTPHandler

    args = parse_args()

    # 加载配置文件
    config = load_config(args.config)

    # 获取端口配置
    ports_config = get_ports_config(config)

    # 使用命令行参数覆盖配置文件中的端口设置
    tcp_port = args.tcp_port if args.tcp_port is not None else ports_config.get("tcp", 9000)
    http_port = args.http_port if args.http_port is not None else ports_config.get("http", 8080)
    https_port = args.https_port if args.https_port is not None else ports_config.get("https", 8443)
    ssh_port = args.ssh_port if args.ssh_port is not None else ports_config.get("ssh", 2222)
    telnet_port = args.telnet_port if args.telnet_port is not None else ports_config.get("telnet", 2323)
    ftp_port = args.ftp_port if args.ftp_port is not None else ports_config.get("ftp", 2121)

    # 如果需要，确保证书存在
    certfile = Path(args.certfile)
    keyfile = Path(args.keyfile)
    if args.generate_cert:
        ok = ensure_self_signed(certfile, keyfile)
        if not ok:
            op_logger.warning("没有有效的证书/密钥，HTTPS将失败。继续运行。")

    # 实例化处理器
    handlers = []
    handlers.append(TCPHandler(host=args.host, port=tcp_port, log_file=args.log))
    handlers.append(HTTPHandler(host=args.host, port=http_port, log_file=args.log))
    handlers.append(HTTPSHandler(host=args.host, port=https_port, log_file=args.log, certfile=str(certfile), keyfile=str(keyfile)))
    handlers.append(SSHHandler(host=args.host, port=ssh_port, log_file=args.log, config=config))
    handlers.append(TelnetHandler(host=args.host, port=telnet_port, log_file=args.log, config=config))
    handlers.append(FTPHandler(host=args.host, port=ftp_port, log_file=args.log))

    manager = HoneypotManager(handlers)
    await manager.start()

    # 运行直到被中断
    try:
        # 主线程保持运行状态
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        op_logger.info("收到键盘中断；正在关闭")
    finally:
        await manager.stop()

def main():
    """
    程序主入口函数
    """
    try:
        # 创建新的事件循环用于主线程
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(main_async())
    except Exception as e:
        op_logger.exception("致命错误: %s", e)
        sys.exit(1)

if __name__ == "__main__":
    main()
